package com.fit.spring.boot.aop.interceptor.autoconfigure;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.aopalliance.intercept.MethodInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

import com.fit.spring.boot.aop.annotation.Notice;
import com.fit.spring.boot.aop.interceptor.NoticeInterceptor;
import com.fit.spring.boot.aop.notice.GainType;
import com.fit.spring.boot.aop.notice.Notification;
import com.fit.spring.boot.proxy.interceptor.extension.Config;
import com.fit.spring.boot.proxy.interceptor.extension.InterceptorConfigurationAware;

/**
 * 通知拦截器配置
 * @author hcl
 *
 */
public class AopInterceptorAutoConfiguration extends InterceptorConfigurationAware{

	private static final Logger log = LoggerFactory.getLogger(AopInterceptorAutoConfiguration.class);
	
	public static final String PARAM_KEY = "notification";
	
	/**
	 * context对象
	 */
	@Autowired
	private ApplicationContext context;
	
	@Override
	public MethodInterceptor registeredInterceptor() {
		return new NoticeInterceptor();
	}

	@SuppressWarnings("unchecked")
	@Override
	public boolean isMethodInterceptor(Config config, Map<String, Annotation> annotations) {
		Notice ann = (Notice)annotations.get(Notice.class.getName());
		List<Class<? extends Notification>> classList = new ArrayList<Class<? extends Notification>>();
		
		String[] noticeClassNames = ann.noticeClassNames();
		for(String noticeClassName : noticeClassNames){
			try {
				classList.add((Class<? extends Notification>) Class.forName(noticeClassName));
			} catch (ClassNotFoundException e) {
				throw new RuntimeException("通知拦截器配置异常！'"+noticeClassName+"' 没有找到。",e);
			}
		}
		
		Class<? extends Notification>[] clazzs = ann.noticeClass();
		
		for(Class<? extends Notification> clazz : clazzs){
			classList.add(clazz);
		}
		
		if(classList.size() == 0){
			throw new RuntimeException("通知拦截器配置异常！@Notice的noticeClass属性不能为空！ ");
		}
		
		
		List<Notification> notifs = new ArrayList<Notification>();
		for(Class<? extends Notification> notifClass : classList){
			if(!notifClass.isAssignableFrom(Notification.class)){
				throw new RuntimeException("通知拦截器配置异常！'"+notifClass.getName()+"' 不是 '"+Notification.class.getName()+"'的实现者！");
			}
			GainType gainType = ann.gainType();
			
			Notification notif = null;
			if(gainType == GainType.AUTO){
				try{
					notif = this.getSpringNotification(notifClass);
				}catch(Exception e){
					if(log.isDebugEnabled()){
						log.debug("通知拦截器配置异常！spring中未获取到：{},已自动跳过！",Notification.class.getName(),e);
					}
				}
				if(notif == null){
					try {
						notif = this.createNotification(notifClass);
					} catch (Exception e) {
						throw new RuntimeException("通知拦截器配置异常！自动创建'"+notifClass.getName()+"' 异常！",e);
					}
				}
				
			}else if(gainType == GainType.SPRING){
				try{
					notif = this.getSpringNotification(notifClass);
				}catch(Exception e){
					throw new RuntimeException("通知拦截器配置异常！spring中未获取到：'"+notifClass.getName()+"'！",e);
				}
				
				
			}else{
				try {
					notif = this.createNotification(notifClass);
				} catch (Exception e) {
					throw new RuntimeException("通知拦截器配置异常！自动创建'"+notifClass.getName()+"' 异常！",e);
				}
			}
			notifs.add(notif);
		}
		
		config.put(PARAM_KEY, notifs);
		
		return true;
	}

	@SuppressWarnings("unchecked")
	@Override
	public Class<Annotation>[] getTargetAnnotations() {
		return new Class[]{Notice.class};
	}

	/**
	 * 从spring容器中获取
	 * @param clazz
	 * @return
	 */
	private Notification getSpringNotification(Class<?> clazz){
		return (Notification)context.getBean(clazz);
	}
	
	
	/**
	 * 自动创建
	 * @param clazz
	 * @return
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	private Notification createNotification(Class<?> clazz) throws InstantiationException, IllegalAccessException{
		return (Notification)clazz.newInstance();
	}
	
}
